package com.example.scale;

import java.io.IOException;

import org.andengine.engine.camera.hud.HUD;
import org.andengine.engine.camera.hud.controls.AnalogOnScreenControl;
import org.andengine.engine.camera.hud.controls.AnalogOnScreenControl.IAnalogOnScreenControlListener;
import org.andengine.engine.camera.hud.controls.BaseOnScreenControl;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.AlphaModifier;
import org.andengine.entity.modifier.LoopEntityModifier;
import org.andengine.entity.modifier.RotationModifier;
import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.CameraScene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.entity.text.TextOptions;
import org.andengine.extension.physics.box2d.FixedStepPhysicsWorld;
import org.andengine.extension.physics.box2d.PhysicsConnector;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITiledTextureRegion;
import org.andengine.util.SAXUtils;
import org.andengine.util.adt.align.HorizontalAlign;
import org.andengine.util.adt.color.Color;
import org.andengine.util.level.EntityLoader;
import org.andengine.util.level.constants.LevelConstants;
import org.andengine.util.level.simple.SimpleLevelEntityLoaderData;
import org.andengine.util.level.simple.SimpleLevelLoader;
import org.xml.sax.Attributes;

import android.opengl.GLES20;
import android.util.Log;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.Manifold;
import com.example.scale.SceneManager.SceneType;

public class GameScene extends BaseScene {

	private HUD gameHUD;
	// private Text scoreText;
	// private int score = 0;
	public static PhysicsWorld physicsWorld;
	public static Vector2 worldGravity = new Vector2(0, -17);

	// Variables for level loader
	private static final String TAG_LEVEL_ATTRIBUTE_MIN_SCREEN_Y = "minCamY";

	private static final String TAG_ENTITY = "entity";
	private static final String TAG_ENTITY_ATTRIBUTE_X = "x";
	private static final String TAG_ENTITY_ATTRIBUTE_Y = "y";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE = "type";
	private static final String TAG_ENTITY_ATTRIBUTE_WIDTH = "width";
	private static final String TAG_ENTITY_ATTRIBUTE_HEIGHT = "height";
	private static final String TAG_ENTITY_ATTRIBUTE_WORDS = "words";
	private static final String TAG_ENTITY_ATTRIBUTE_RANGE = "range";
	private static final String TAG_ENTITY_ATTRIBUTE_DELAY = "delay";
	private static final String TAG_ENTITY_ATTRIBUTE_COLLIDE_WITH = "collideWith";
	private static final String TAG_ENTITY_ATTRIBUTE_POPUP_PURPOSE = "purpose";

	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_MOVING_PLATFORM = "movingPlatform";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_MOVING_BOX = "movingBox";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_RECTANGLE = "rectangle";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_TEXT = "text";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLAYER = "player";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_SPIKES = "spikes";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_POPUP = "popup";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_POWERUP = "powerup";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_TURRET = "turret";
	private static final String TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_DRONE = "drone";
	public static Player player;

	// Game Over
	private Text gameOverText;
	private boolean gameOverDisplayed;

	// Level End
	private Text levelEndText;
	private Rectangle levelEndRectangle;
	private boolean levelEndDisplayed;
	
	private int numPowerupsCollected;

	private ContactListener contactListener;

	// Rectangles for buttons
	private Rectangle buttonScaleArea;
	private Rectangle buttonMoveArea;
	private Rectangle leftArea;
	private Rectangle rightArea;
	private Rectangle jumpButtonArea;
	private Rectangle pauseButtonArea;
	
	// Collision Detectors
	private Rectangle collideRightIndicator;
	private Rectangle collideLeftIndicator;
	private Rectangle collideTopIndicator;
	private Rectangle collideBottomIndicator;
	private static boolean debugCollision = false;

	// Popup scene for hints, dialogue
	private CameraScene mPopupScene;
	private Rectangle hintRectangle;
	private Sprite dialogueRectangle;
	private boolean popupIsShowing;
	private Rectangle popupArea;
	public Text popupText;
	public Object[][] popupTable;
	private int popupIndex;
	public boolean showHints;

	// Pause scene
	private CameraScene mPauseScene;
	private boolean isPaused;
	private Sprite pauseButton;
	private Sprite playButton;

	// Saved preferences
	private SavedData mySavedData;
	private boolean storyBoxChecked;
	private boolean hintBoxChecked;
	private int controlMethod;
	private boolean levelCompleteArray[];
	private int levelPowerupsArray[];
	private int playerExperience;
	
	private static int POWERUP_EXPERIENCE_BONUS = 50;
	private static int LEVEL_COMPLETE_EXPERIENCE_BONUS = 200;

	// Control Method Integers
	private static final int ARROW_CONTROL = 0;
	private static final int JOYSTICK_CONTROL = 1;
	private static final int SLIDER_CONTROL = 2;

	// HUD regions
	private AnalogOnScreenControl analogOnScreenControl;
	private Rectangle slideMove;
	private Rectangle buttonMoveVisible;
	private Rectangle slideScale;
	private Rectangle buttonScaleVisible;
	private Sprite jumpButtonVisible;
	private Sprite left;
	private Sprite right;
	private Rectangle scaleMeterBackground;
	private Rectangle scaleMeterBar;

	// Level bounds
	public int minCameraY; // The minimum value camera y-value. Used
							// for the character's death from
							// falling
	public int levelWidth;

	// Slow Motion Variables
	private boolean slowMotionActive;

	@Override
	public void createScene() {
		minCameraY = 0;
		gameOverDisplayed = false;
		levelEndDisplayed = false;
		slowMotionActive = false;
		// Load saved preferences
		loadPrefs();
		loadProgress();

		createBackground();
		popupIndex = 0;
		
		numPowerupsCollected = 0;

		createPopupScene();

		createPauseScene();

		createPhysics();
		loadLevel(SceneManager.getInstance().whichLevel); // Load
		// asset/lvl/whichLevel.txt
		createHUD();

		if (controlMethod == JOYSTICK_CONTROL) {
			analogControl();
		}
		createGameOverText();
		gameOverDisplayed = false;
	}

	private void loadPrefs() {
		mySavedData = new SavedData(activity);
		mySavedData.loadPrefData();
		storyBoxChecked = mySavedData.togglePlotValue;
		hintBoxChecked = mySavedData.toggleHintsValue;
		controlMethod = mySavedData.controlMethodValue;
	}

	private void loadProgress() {
		levelCompleteArray = new boolean[LevelSelectScene.numLevels + 1];
		levelPowerupsArray = new int[LevelSelectScene.numLevels];
		mySavedData.loadProgressData();
		
		for (int i = 1; i <= LevelSelectScene.numLevels; i++) {
			levelCompleteArray[i - 1] = mySavedData.levelCompleteArray[i - 1];
		}
		for(int i = 0; i< LevelSelectScene.numLevels; i++) {
			levelPowerupsArray[i] = mySavedData.levelPowerupsCollected[i];
		}
		playerExperience = mySavedData.playerExperience;
	}

	private void createLevelEndSprite() {
		levelEndRectangle = new Rectangle(0, 0, GameActivity.CAMERA_WIDTH - 50,
				GameActivity.CAMERA_HEIGHT / 2, vbom);
		levelEndRectangle.setPosition(camera.getCenterX(), camera.getCenterY());
		levelEndRectangle.setColor(Color.BLACK);
		if (SceneManager.getInstance().whichLevel < LevelSelectScene.numLevels) {
			levelEndText = new Text(0, 0, resourcesManager.font,
					"Level Complete", vbom);
		} else {
			levelEndText = new Text(0, 0, resourcesManager.font,
					"Game Complete", vbom);
		}
		levelEndText.setPosition(camera.getCenterX(), camera.getCenterY());
		levelEndText.setColor(Color.WHITE);
	}

	private void createPopupScene() {
		// 
		showHints = false;
		mPopupScene = new CameraScene(camera);
		hintRectangle = new Rectangle(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2, GameActivity.CAMERA_WIDTH - 50,
				GameActivity.CAMERA_HEIGHT / 2, vbom);
		hintRectangle.setColor(Color.BLACK);
		// hintRectangle.setAlpha(.8f);
		mPopupScene.attachChild(hintRectangle);
		
		// Screen is 800 x 480?
		dialogueRectangle = new Sprite(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2, resourcesManager.dialogue_card_region,
				vbom);
		mPopupScene.attachChild(dialogueRectangle);

		popupText = new Text(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2, resourcesManager.font,
				"Use the controls in the \n bottom left corner to move.",
				new TextOptions(HorizontalAlign.CENTER), vbom);
		mPopupScene.attachChild(popupText);

		mPopupScene.setBackgroundEnabled(false);
		popupTable = new Object[10][5];
		/* Popup Table stores information about all of the dialogue and hints in a level
		popupTable[i][0]: If popup has been shown already
		popupTable[i][1]: X Position
		popupTable[i][2]: Delay
		popupTable[i][3]: Text to Display
		popupTable[i][4]: Purpose (Dialogue or Hint) */
		for (int i = 0; i < popupTable.length; i++) {
			popupTable[i][0] = true;
			popupTable[i][1] = 0;
			popupTable[i][2] = 0;
			popupTable[i][3] = " ";
			popupTable[i][4] = " ";
		}
	}

	private void createPauseScene() {
		// Set up pause scene
		mPauseScene = new CameraScene(camera);
		final Text pauseText = new Text(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2, resourcesManager.font,
				"PAUSED", new TextOptions(HorizontalAlign.CENTER), vbom);
		mPauseScene.attachChild(pauseText);

		mPauseScene.setBackgroundEnabled(false);
	}

	@Override
	public void onBackKeyPressed() {
		camera.setZoomFactor(1);
		SceneManager.getInstance().gameScene.disposeScene();
		ResourcesManager.getInstance().unloadGameTextures();
		SceneManager.getInstance().loadLevelSelectScene();
	}

	@Override
	public SceneType getSceneType() {
		return SceneType.SCENE_GAME;
	}

	@Override
	public void disposeScene() {
		camera.setHUD(null);
		camera.setCenter(400, 240);
		// So that camera doesn't continue following player position after
		// return to menu
		camera.setChaseEntity(null);
	}

	// Set the background of the screen to blue. Can also use an image or a
	// parallax background
	private void createBackground() {
		setBackground(new Background(Color.WHITE));
	}

	// Analog joystick controller to control the player's movement
	private void analogControl() {
		final int AnalogX = 120;
		analogOnScreenControl = new AnalogOnScreenControl(AnalogX, 70, camera,
				ResourcesManager.base_region, ResourcesManager.knob_region,
				0.1f, 200, vbom, new IAnalogOnScreenControlListener() {
					@Override
					public void onControlChange(
							final BaseOnScreenControl pBaseOnScreenControl,
							final float pValueX, final float pValueY) {
						if (pValueX == 0 && player.footContacts >= 1) {
							player.stopRunning();
							player.goingLeft = false;
							player.goingRight = false;
						}
						if (!isPaused && player.alive) {
							// Character was going left, but now is going right
							if (player.goingLeft && !player.goingRight
									&& pValueX > 0.0f) {
								player.goingRight = true;
								player.goingLeft = false;
								player.facingRight = true;
								player.facingLeft = false;
								player.flipSpriteRight();
								if (player.footContacts >= 1) { // Animate
																// running
																// if he's on
																// the
																// ground
									//player.setRunning();
									player.setPlayerAnimation("running");
									player.animate(125, 0, 12, true);
								} else {
									//player.setJumping();
									player.setPlayerAnimation("jumpingForward");
									player.animate(250, 0, 7, false);
								}
							} // Character was going right, but now left
							else if (!player.goingLeft && player.goingRight
									&& pValueX < 0.0f) {
								player.goingRight = false;
								player.goingLeft = true;
								player.facingRight = false;
								player.facingLeft = true;
								player.changeScaleX(-Math.abs(player.getScaledWidth()));
								if (player.footContacts >= 1) { // Animate
																// running
																// if he's on
																// the
																// ground
									//player.setRunning();
									player.setPlayerAnimation("running");
									player.animate(125, 0, 12, true);
								} else {
									//player.setJumping();
									player.setPlayerAnimation("jumpingForward");
									player.animate(250, 0, 7, false);
								}
//								if (player.footContacts == 1) { // Animate
//																// running
//																// if he's on
//																// the
//																// ground
//									player.setRunning();
//								} else {
//									player.setJumping();
//								}
							} // Character wasn't moving previously
							else if (!player.goingLeft && !player.goingRight) {
								// Character is moving left now
								if (pValueX < 0.0f) {
									player.goingRight = false;
									player.goingLeft = true;
									player.facingRight = false;
									player.facingLeft = true;
									player.changeScaleX(-Math.abs(player.getScaledWidth()));
									if (player.footContacts >= 1) { // Animate
																	// running
																	// if he's on
																	// the
																	// ground
										//player.setRunning();
										player.setPlayerAnimation("running");
										player.animate(125, 0, 12, true);
									} else {
										//player.setJumping();
										player.setPlayerAnimation("jumpingForward");
										player.animate(250, 0, 7, false);
									}
//									if (player.footContacts == 1) { // Animate
//																	// running
//																	// if
//																	// he's on
//																	// the
//																	// ground
//										player.setRunning();
//									} else {
//										player.setJumping();
//									}
								} // Character is moving right now
								else if (pValueX > 0.0f) {
									player.goingRight = true;
									player.goingLeft = false;
									player.facingRight = true;
									player.facingLeft = false;
									player.flipSpriteRight();
									if (player.footContacts >= 1) { // Animate
																	// running
																	// if he's on
																	// the
																	// ground
										//player.setRunning();
										player.setPlayerAnimation("running");
										player.animate(125, 0, 12, true);
									} else {
										//player.setJumping();
										player.setPlayerAnimation("jumpingForward");
										player.animate(250, 0, 7, false);
									}
//									if (player.footContacts == 1) { // Animate
//																	// running
//																	// if
//																	// he's on
//																	// the
//																	// ground
//										player.setRunning();
//									} else {
//										player.setJumping();
//									}
								}
							}
							player.changeVelocity((float) ((pValueX) * 10 * Math.sqrt(player
									.getScaleY())), player.body
									.getLinearVelocity().y);
							/*player.body.setLinearVelocity(new Vector2(
									(float) ((pValueX) * 10 * Math.sqrt(player
											.getScaleY())), player.body
											.getLinearVelocity().y));*/
							/*
							 * player.body.setLinearVelocity(new Vector2(
							 * (float) (pValueX Math.sqrt(player.getScaleY()) *
							 * 5), player.body.getLinearVelocity().y));
							 */
						}
					}

					@Override
					public void onControlClick(
							final AnalogOnScreenControl pAnalogOnScreenControl) {

					}
				});
		analogOnScreenControl.getControlBase().setBlendFunction(
				GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
		analogOnScreenControl.getControlBase().setAlpha(0.5f);
		analogOnScreenControl.getControlKnob().setAlpha(0.5f);

		analogOnScreenControl.refreshControlKnobPosition();

		// attachChild(analogOnScreenControl);
		// registerTouchArea(analogOnScreenControl);
		// analogOnScreenControl.setTouchAreaBindingOnActionMoveEnabled(true);
		// analogOnScreenControl.setTouchAreaBindingOnActionDownEnabled(true);

		setChildScene(analogOnScreenControl);
	}

	private void createHUD() {
		gameHUD = new HUD();

		final Rectangle filter = new Rectangle(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2, GameActivity.CAMERA_WIDTH,
				GameActivity.CAMERA_HEIGHT, vbom);
		filter.setColor(Color.BLACK);
		filter.setAlpha(0.3f);
		gameHUD.attachChild(filter);

		// Create score text. Prepare memory with long score
		/*
		 * scoreText = new Text(20, 420, resourcesManager.font,
		 * "Score: 0123456789", new TextOptions(HorizontalAlign.LEFT), vbom);
		 * scoreText.setColor(Color.WHITE); scoreText.setAnchorCenter(0, 0);
		 * scoreText.setText("Score: 0"); gameHUD.attachChild(scoreText);
		 */

		/*
		 * Create a slider for moving the character: slide is the background
		 * rectangle of the slider buttonVisible is the visible part of the
		 * slider that moves buttonArea is the touch area surrounding the whole
		 * slider that detects touches
		 */
		if (controlMethod == SLIDER_CONTROL) {
			slideMove = new Rectangle(150, 50, 200, 10, vbom);
			buttonMoveVisible = new Rectangle(slideMove.getX(),
					slideMove.getY(), 40, 40, vbom);
			buttonMoveArea = new Rectangle(slideMove.getX() + 80,
					slideMove.getY(), 480, 150, vbom) {
				public boolean onAreaTouched(TouchEvent touchEvent,
						float touchX, float touchY) {
					if (!isPaused && player.alive && !popupIsShowing) {
						if (touchEvent.getAction() == TouchEvent.ACTION_DOWN
								|| touchEvent.getAction() == TouchEvent.ACTION_MOVE) {
							int newState = player.playerState;
							// Character was going left, but now is going right
							if (player.goingLeft && !player.goingRight
									&& touchEvent.getX() > slideMove.getX()) {
								player.goingRight = true;
								player.goingLeft = false;
								player.facingRight = true;
								player.facingLeft = false;
								player.flipSpriteRight();
								if (player.footContacts >= 1) { // Animate
																// running
																// if he's on
																// the
																// ground
									//player.setRunning();
									// If the player isn't already running, set him to that
									/*if (player.playerState != Player.RUNNING) {
										player.setPlayerAnimation("running");
										player.animate(125, 0, 12, true);
									}*/
									newState = Player.RUNNING;
								} else {
									//player.setJumping();
									/*player.setPlayerAnimation("jumpingForward");
									player.animate(250, 0, 7, false);*/
									newState = Player.JUMPING_FORWARD;
								}
	//							if (player.footContacts == 1) { // Animate running
	//															// if he's on the
	//															// ground
	//								player.setRunning();
	//							} else {
	//								player.setJumping();
	//							}
							} 
							// Character was going right, but now left
							else if (!player.goingLeft && player.goingRight
									&& touchEvent.getX() < slideMove.getX()) {
								player.goingRight = false;
								player.goingLeft = true;
								player.facingRight = false;
								player.facingLeft = true;
								//player.changeScaleX(-Math.abs(player.getScaledWidth()));
								player.flipSpriteLeft();
								if (player.footContacts >= 1) { // Animate
																// running
																// if he's on
																// the
																// ground
									//player.setRunning();
									/*player.setPlayerAnimation("running");
									player.animate(80, 0, 12, true);*/
									newState = Player.RUNNING;
								} else {
									//player.setJumping();
									/*player.setPlayerAnimation("jumpingForward");
									player.animate(250, 0, 7, false);*/
									newState = Player.JUMPING_FORWARD;
								}
	//							if (player.footContacts == 1) { // Animate running
	//															// if he's on the
	//															// ground
	//								player.setRunning();
	//							} else {
	//								player.setJumping();
	//							}
							} 
							// Character wasn't moving
							else if (!player.goingLeft && !player.goingRight) {
								// Character wasn't moving but is moving left now
								if (touchEvent.getX() < slideMove.getX()) {
									if (!player.facingLeft) {
										player.flipSpriteLeft();
									}
									player.goingRight = false;
									player.goingLeft = true;
									player.facingRight = false;
									player.facingLeft = true;
									// TODO: WHY NO WORK?
									//player.changeScaleX(-Math.abs(player.getScaledWidth()));
									if (player.footContacts >= 1) { // Animate
																	// running
																	// if he's on
																	// the
																	// ground
										//player.setRunning();
										/*player.setPlayerAnimation("running");
										player.animate(125, 0, 12, true);*/
										newState = Player.RUNNING;
									} else {
										//player.setJumping();
										/*player.setPlayerAnimation("jumpingForward");
										player.animate(250, 0, 7, false);*/
										newState = Player.JUMPING_FORWARD;
									}
	//								if (player.footContacts == 1) { // Animate
	//																// running if
	//																// he's on the
	//																// ground
	//									player.setRunning();
	//								} else {
	//									player.setJumping();
	//								}
								} 
								// Character wasn't moving but is moving right now
								else if (touchEvent.getX() > slideMove.getX()) {
									// TODO: HERE is where running is set initially
									if (!player.facingRight) { 
										player.flipSpriteRight();
									}
									player.goingRight = true;
									player.goingLeft = false;
									player.facingRight = true;
									player.facingLeft = false;
									//player.setScaleX(Math.abs(player.getScaleX())); // Make sprite face right
									if (player.footContacts >= 1) { // Animate
																	// running
																	// if he's on
																	// the
																	// ground
										//player.setRunning();
										/*player.setPlayerAnimation("running");
										player.animate(80, 0, 12, true);*/
										newState = Player.RUNNING;
										// Change animation speed based on how fast moving
										/*player.animate(250/((int) (buttonMoveVisible.getX() - slideMove
														.getX())), 0, 7, false);*/
									} else {
										//player.setJumping();
										/*player.setPlayerAnimation("jumpingForward");
										player.animate(250, 0, 7, false);*/
										newState = Player.JUMPING_FORWARD;
									}
								}
							}
							
							buttonMoveVisible.setScale(1.25f);
							// If touch is within slider
							if (touchEvent.getX() > slideMove.getX()
									- (slideMove.getWidth() / 2)
									+ buttonMoveVisible.getWidth() / 2
									&& touchEvent.getX() < slideMove.getX()
											+ (slideMove.getWidth() / 2)
											- buttonMoveVisible.getWidth() / 2) {
								buttonMoveVisible.setX(touchEvent.getX());
							} // If touch is past the edge of the slider
							else if (touchEvent.getX() < slideMove.getX()
									- (slideMove.getWidth() / 2)
									+ buttonMoveVisible.getWidth() / 2) {
								buttonMoveVisible.setX(slideMove.getX()
										- (slideMove.getWidth() / 2)
										+ buttonMoveVisible.getWidth() / 2);
							} else if (touchEvent.getX() > slideMove.getX()
									+ (slideMove.getWidth() / 2)
									- buttonMoveVisible.getWidth() / 2) {
								buttonMoveVisible.setX(slideMove.getX()
										+ (slideMove.getWidth() / 2)
										- buttonMoveVisible.getWidth() / 2);
							}
							
							player.setRunning((float) ((buttonMoveVisible.getX() - slideMove
									.getX()) / 8 * Math
									.sqrt(player.getScaleY())), newState);
							/*Log.d("Setting linear velocity x value to: ", Float.toString((float) ((buttonMoveVisible.getX() - slideMove
									.getX()) / 8 * Math
									.sqrt(player.getScaleY()))));*/
							/*player.changeVelocity((float) ((buttonMoveVisible.getX() - slideMove
													.getX()) / 8 * Math
													.sqrt(player.getScaleY())),
											player.body.getLinearVelocity().y);*/
							/*player.body
									.setLinearVelocity(new Vector2(
											(float) ((buttonMoveVisible.getX() - slideMove
													.getX()) / 8 * Math
													.sqrt(player.getScaleY())),
											player.body.getLinearVelocity().y));*/
							// Adjust the player's animation if he's changed state
							/*if (newState != player.playerState) {
								if (newState == Player.RUNNING) {
									player.setPlayerAnimation("running");
									player.animate(80, 0, 12, true);
								} else {
									player.setPlayerAnimation("jumpingForward");
									player.animate(250, 0, 7, false);
								}
								player.playerState = newState;
							}*/
						}
						if (touchEvent.getAction() == TouchEvent.ACTION_UP
								|| touchEvent.getAction() == TouchEvent.ACTION_CANCEL
								|| touchEvent.getAction() == TouchEvent.ACTION_OUTSIDE) {
							// TODO
							buttonMoveVisible.setScale(1);
							buttonMoveVisible.setX(slideMove.getX()); // Reset
																		// the
																		// slider
							// To make character stop immediately when release
							// slider, instead of sliding:
							// DECIDE WHETHER CHARACTER SLIDES:
							/*player.body.setLinearVelocity(new Vector2(0,
									player.body.getLinearVelocity().y));*/
							player.stopRunning();
						}
					}
					return true;
				}
			};
			buttonMoveVisible.setColor(Color.WHITE);
			slideMove.setColor(Color.WHITE);
			buttonMoveVisible.setAlpha(0.5f);
			slideMove.setAlpha(0.5f);
			buttonMoveArea.setAlpha(0);

			gameHUD.attachChild(slideMove);
			gameHUD.attachChild(buttonMoveVisible);
			gameHUD.attachChild(buttonMoveArea);
			gameHUD.registerTouchArea(buttonMoveArea);
		}

		/////////////////////////////////////////////////////////////////////
		// SCALE SLIDER
		/////////////////////////////////////////////////////////////////////
		// Only add scale items if not the first level or it's already completed
		if (SceneManager.getInstance().whichLevel > 1
				|| levelCompleteArray[1] == true) {
			/*
			 * Create a slider for changing the size of the character: slide is
			 * the background rectangle of the slider buttonVisible is the
			 * visible part of the slider that moves buttonArea is the touch
			 * area surrounding the whole slider that detects touches
			 */
			slideScale = new Rectangle(750, 120, 10, 200, vbom);
			// final Sprite buttonScaleVisible = new Sprite(slideScale.getX(),
			// slideScale.getY(), ResourcesManager.circle_region, vbom);
			// buttonScaleVisible.setScale(1.25f);
			buttonScaleVisible = new Rectangle(slideScale.getX(),
					slideScale.getY(), 40, 40, vbom);
			buttonScaleArea = new Rectangle(slideScale.getX(),
					slideScale.getY(), 120, 120, vbom) {
				public boolean onAreaTouched(TouchEvent touchEvent,
						float touchX, float touchY) {
					if (!isPaused && player.alive && !popupIsShowing) {
						if (touchEvent.getAction() == TouchEvent.ACTION_DOWN
								|| touchEvent.getAction() == TouchEvent.ACTION_MOVE) {
							slowMotionActive = true;
							buttonScaleVisible.setScale(1.25f);
							if (touchEvent.getY() <= buttonScaleVisible.getY()) { // Scaling
																					// down,
																					// set
																					// colliders
																					// to
																					// false
								player.collidingBottom = false;
								player.collidingRight = false;
								player.collidingTop = false;
								player.collidingLeft = false;
								if(debugCollision) {
									collideRightIndicator.setColor(Color.GREEN);
									collideLeftIndicator.setColor(Color.GREEN);
									collideBottomIndicator.setColor(Color.GREEN);
									collideTopIndicator.setColor(Color.GREEN);
								}
							}
							if (touchEvent.getY() <= buttonScaleVisible.getY()
									|| (!(player.collidingBottom && player.collidingTop) && !(player.collidingLeft && player.collidingRight))) {
								if (touchEvent.getY() > slideScale.getY()
										- (slideScale.getHeight() / 2)
										+ buttonScaleVisible.getHeight() / 2
										&& touchEvent.getY() < slideScale
												.getY()
												+ (slideScale.getHeight() / 2)
												- buttonScaleVisible
														.getHeight() / 2) {
									buttonScaleVisible.setY(touchEvent.getY());
								} else if (touchEvent.getY() < slideScale
										.getY()
										- (slideScale.getHeight() / 2)
										+ buttonScaleVisible.getHeight() / 2) {
									buttonScaleVisible.setY(slideScale.getY()
											- (slideScale.getHeight() / 2)
											+ buttonScaleVisible.getHeight()
											/ 2);
								} else if (touchEvent.getY() > slideScale
										.getY()
										+ (slideScale.getHeight() / 2)
										- buttonScaleVisible.getHeight() / 2) {
									buttonScaleVisible.setY(slideScale.getY()
											+ (slideScale.getHeight() / 2)
											- buttonScaleVisible.getHeight()
											/ 2);
								}
								if (touchEvent.getY() > slideScale.getY()) {
									player.scaling = true;
								} else {
									player.scaling = false;
								}
								buttonScaleArea.setY(buttonScaleVisible.getY());
								Vector2 playerVelocity = player.body
										.getLinearVelocity(); // Get the initial
																// velocity
								float oldScale = player.getScaleY();
								float newScale = (float) (player.playerScale * (Math.pow(
										1 + (buttonScaleVisible.getY() - slideScale.getY())
										/ (slideScale.getHeight()), 4)));
								if (player.facingLeft || player.goingLeft) {
									// Problem with changeScaleY, so we use changeScale, then flip the X if facing left
									//player.changeScaleXY(-newScale, newScale);
									player.changeScale(newScale);
									player.changeScaleX(-newScale);
								} else {
									player.changeScale(newScale)
									;
								}
								//player.changeScaleX(newScale);
								
								/*player.setScale((float) (player.playerScale * (Math.pow(
										1
												+ (buttonScaleVisible.getY() - slideScale
														.getY())
												/ (slideScale.getHeight()), 4))));
								final PhysicsConnector pc = physicsWorld
										.getPhysicsConnectorManager()
										.findPhysicsConnectorByShape(player);
								physicsWorld.unregisterPhysicsConnector(pc);
								physicsWorld.destroyBody(player.body);
								player.createPhysics(camera, physicsWorld);
								physicsWorld
										.registerPhysicsConnector(new PhysicsConnector(
												player, player.body, true,
												false) {
											// Use onUpdate method to help
											// reduce
											// camera jittering when moving
											@Override
											public void onUpdate(
													float pSecondsElapsed) {
												super.onUpdate(pSecondsElapsed);
												camera.onUpdate(0.1f);
											}
										});*/
								/*
								 * Player.body =
								 * PhysicsFactory.createBoxBody(physicsWorld,
								 * player, BodyType.DynamicBody,
								 * PhysicsFactory.createFixtureDef(0, 0, 0));
								 * physicsWorld.registerPhysicsConnector(new
								 * PhysicsConnector( player, Player.body, true,
								 * false) { // Could set fixture def to 0, .05,
								 * .02 // Use onUpdate method to help reduce
								 * camera jittering when moving
								 * 
								 * @Override public void onUpdate(float
								 * pSecondsElapsed) {
								 * super.onUpdate(pSecondsElapsed);
								 * camera.onUpdate(0.1f);
								 * 
								 * // Check if character falls beneath the level
								 * if (Player.body.getPosition().y <= 0) { if
								 * (!gameOverDisplayed) { displayGameOverText();
								 * } } } });
								 */
								if (controlMethod == ARROW_CONTROL) {
									if (player.goingRight) {
										player.changeVelocity((float) (10 * Math.sqrt(player
																.getScaleY())),
														player.body
																.getLinearVelocity().y);
									} else if (player.goingLeft) {
										player.changeVelocity((float) (-10 * Math.sqrt(player
												.getScaleY())), player.body
												.getLinearVelocity().y);
									}
								} else if (controlMethod == SLIDER_CONTROL) {
									player.changeVelocity((float) ((buttonMoveVisible.getX() - slideMove
											.getX()) / 8 * Math
											.sqrt(player.getScaleY())), playerVelocity.y);
								} else if (controlMethod == JOYSTICK_CONTROL){
									float oldPValue = (float) (playerVelocity.x/10/Math.pow(oldScale, 2));
									player.changeVelocity((float) ((oldPValue) * 10 * Math.sqrt(player
											.getScaleY())), player.body
											.getLinearVelocity().y);
								}
								// Player.body.setUserData("player");
								// Zoom the camera in/out based on the scale
								camera.setZoomFactor((float) (1 / (Math.pow(
										1+(buttonScaleVisible.getY() - slideScale.getY())
												/ (slideScale.getHeight()), .75))));
							}
						}
						if (touchEvent.getAction() == TouchEvent.ACTION_UP
								|| touchEvent.getAction() == TouchEvent.ACTION_CANCEL
								|| touchEvent.getAction() == TouchEvent.ACTION_OUTSIDE) {
							slowMotionActive = false;
							buttonScaleVisible.setScale(1);
						}
					}
					return true;
				}
			};
			// buttonScaleVisible.setColor(Color.WHITE);
			slideScale.setColor(Color.WHITE);
			buttonScaleVisible.setAlpha(0.4f);
			slideScale.setAlpha(0.5f);
			buttonScaleArea.setAlpha(0);

			// setTouchAreaBindingOnActionMoveEnabled(true);
			// setTouchAreaBindingOnActionDownEnabled(true);

			gameHUD.attachChild(slideScale);
			gameHUD.attachChild(buttonScaleVisible);
			gameHUD.attachChild(buttonScaleArea);
			gameHUD.registerTouchArea(buttonScaleArea);

			// Scale Meter
			scaleMeterBackground = new Rectangle(710, 460,
					player.maxScaleMeterAmount, 10, vbom);
			scaleMeterBar = new Rectangle(scaleMeterBackground.getX()
					- (player.maxScaleMeterAmount / 2)
					+ (player.scaleMeterAmount / 2), 460,
					player.scaleMeterAmount, 10, vbom);
			scaleMeterBackground.setColor(Color.BLACK);
			scaleMeterBar.setColor(Color.WHITE);
			scaleMeterBackground.setAlpha(0.6f);
			gameHUD.attachChild(scaleMeterBackground);
			gameHUD.attachChild(scaleMeterBar);
		} else {
			scaleMeterBackground = new Rectangle(710, 460,
					player.maxScaleMeterAmount, 10, vbom);
			scaleMeterBar = new Rectangle(scaleMeterBackground.getX()
					- (player.maxScaleMeterAmount / 2)
					+ (player.scaleMeterAmount / 2), 460,
					player.scaleMeterAmount, 10, vbom);
			slideScale = new Rectangle(750, 120, 10, 200, vbom);
			buttonScaleVisible = new Rectangle(slideScale.getX(),
					slideScale.getY(), 40, 40, vbom);
		}

		/////////////////////////////////////////////////////////////////////
		// JUMP BUTTON
		/////////////////////////////////////////////////////////////////////
		jumpButtonVisible = new Sprite(600, 60, resourcesManager.arrow_region,
				vbom);
		// Larger rectangle that detects touch
		jumpButtonArea = new Rectangle(jumpButtonVisible.getX(),
				jumpButtonVisible.getY(), 120, 150, vbom) {
			public boolean onAreaTouched(TouchEvent touchEvent, float X, float Y) {
				if (!isPaused && player.alive && !popupIsShowing) {
					if (touchEvent.isActionDown()) {
						// TODO
						
						player.jump();
						jumpButtonVisible.setScale(.6f);
					} else if (touchEvent.isActionUp()) {
						jumpButtonVisible.setScale(.55f);
						// Player.body.setLinearVelocity(new Vector2(0,
						// Player.body
						// .getLinearVelocity().y));
					}
				}
				return true;
			}
		};
		gameHUD.registerTouchArea(jumpButtonArea);
		// jumpButtonVisible.setColor(Color.WHITE);
		jumpButtonVisible.setAlpha(0.8f);
		jumpButtonVisible.setScale(.55f);
		jumpButtonArea.setAlpha(0);
		jumpButtonVisible.setRotation(90f);
		gameHUD.attachChild(jumpButtonVisible);
		gameHUD.attachChild(jumpButtonArea);

		pauseButton = new Sprite(45, GameActivity.CAMERA_HEIGHT - 45,
				ResourcesManager.pause_button_region, vbom);
		pauseButtonArea = new Rectangle(pauseButton.getX(), pauseButton.getY(),
				2 * pauseButton.getWidth() / 3,
				2 * pauseButton.getHeight() / 3, vbom) {
			public boolean onAreaTouched(TouchEvent touchEvent, float X, float Y) {
				if (touchEvent.isActionDown()) {
					playButton.setScale(0.55f);
					pauseButton.setScale(.55f);
					if (isPaused && !popupIsShowing) {
						unpauseGame();
					} else {
						if (player.alive) {
							pauseGame();
						}
					}
				} else if (touchEvent.isActionUp()) {
					playButton.setScale(.5f);
					pauseButton.setScale(.5f);
				}
				return true;
			}
		};
		pauseButton.setScale(0.5f);
		pauseButton.setAlpha(0.8f);
		gameHUD.attachChild(pauseButton);
		pauseButtonArea.setAlpha(0);
		gameHUD.attachChild(pauseButtonArea);
		gameHUD.registerTouchArea(pauseButtonArea);

		ResourcesManager.pause_button_region.setCurrentTileIndex(1);
		playButton = new Sprite(45, GameActivity.CAMERA_HEIGHT - 45,
				ResourcesManager.pause_button_region, vbom);
		playButton.setScale(0.5f);
		playButton.setAlpha(0);
		gameHUD.attachChild(playButton);

		// setTouchAreaBindingOnActionMoveEnabled(true);
		// setTouchAreaBindingOnActionDownEnabled(true);

		// L/R Buttons
		if (controlMethod == ARROW_CONTROL) {
			left = new Sprite(50, 45, resourcesManager.arrow_region, vbom);
			right = new Sprite(140, 45, resourcesManager.arrow_region, vbom);
			leftArea = new Rectangle(left.getX(), left.getY(), 80, 80, vbom) {
				public boolean onAreaTouched(TouchEvent touchEvent, float X,
						float Y) {
					if (!isPaused && player.alive && !popupIsShowing) {
						if (touchEvent.isActionDown()) {
							if (player.goingRight) {
								right.setScale(.5f);
								right.setAlpha(0.7f);
							}
							if (!player.goingLeft) {
								player.changeVelocity((float) (-10 * Math.sqrt(player
										.getScaleY())), player.body
										.getLinearVelocity().y);
								/*player.body.setLinearVelocity(new Vector2(
										(float) (-10 * Math.sqrt(player
												.getScaleY())), player.body
												.getLinearVelocity().y));*/
								// player.body.setLinearVelocity(new Vector2(-4,
								// player.body.getLinearVelocity().y));
								player.goingLeft = true;
								player.goingRight = false;
								player.facingRight = false;
								player.facingLeft = true;
								player.changeScaleX(-Math.abs(player.getScaledWidth())); // Make sprite face left
								if (player.footContacts >= 1) { // Animate
																// running
																// if he's on
																// the
																// ground
									//player.setRunning();
									player.setPlayerAnimation("running");
									player.animate(125, 0, 12, true);
								} else {
									//player.setJumping();
									player.setPlayerAnimation("jumpingForward");
									player.animate(250, 0, 7, false);
								}
//								if (player.footContacts == 1) {
//									player.setRunning();
//								} else {
//									player.setJumping();
//								}
								left.setScale(.6f);
								left.setAlpha(0.9f);
							} else {
								player.facingLeft = true;
								//player.stopRunning();
								player.goingLeft = false;
								player.changeVelocity(0, player.body.getLinearVelocity().y);
								/*player.body.setLinearVelocity(new Vector2(0,
										player.body.getLinearVelocity().y));*/
								//player.stopRunning();
								player.setPlayerAnimation("stopped");
								player.stopAnimation(0);
								left.setScale(.5f);
								left.setAlpha(0.7f);
							}
						}
					}
					return true;
				}
			};
			// left.setRotation(90f);
			left.setScale(.5f);
			left.setAlpha(0.7f);
			leftArea.setAlpha(0);

			rightArea = new Rectangle(right.getX(), right.getY(), 80, 80, vbom) {
				public boolean onAreaTouched(TouchEvent touchEvent, float X,
						float Y) {
					if (!isPaused && player.alive && !popupIsShowing) {
						if (touchEvent.isActionDown()) {
							if (player.goingLeft) {
								left.setScale(.5f);
								left.setAlpha(0.7f);
							}
							if (!player.goingRight) {
								player.changeVelocity((float) (10 * Math.sqrt(player
										.getScaleY())), player.body
										.getLinearVelocity().y);
								/*player.body.setLinearVelocity(new Vector2(
										(float) (10 * Math.sqrt(player
												.getScaleY())), player.body
												.getLinearVelocity().y));*/
								player.goingLeft = false;
								player.goingRight = true;
								player.facingRight = true;
								player.facingLeft = false;
								player.flipSpriteRight();
								//player.setScaleX(Math.abs(player.getScaleX())); // Make sprite face right
								if (player.footContacts >= 1) { // Animate
																// running
																// if he's on
																// the
																// ground
									//player.setRunning();
									player.setPlayerAnimation("running");
									player.animate(125, 0, 12, true);
								} else {
									//player.setJumping();
									player.setPlayerAnimation("jumpingForward");
									player.animate(250, 0, 7, false);
								}
//								if (player.footContacts == 1) {
//									player.setRunning();
//								} else {
//									player.setJumping();
//								}
								right.setScale(.6f);
								right.setAlpha(0.9f);
							} else {
								player.facingRight = true;
								//player.stopRunning();
								player.goingRight = false;
								player.changeVelocity(0, player.body
										.getLinearVelocity().y);
								/*player.body.setLinearVelocity(new Vector2(0,
										player.body.getLinearVelocity().y));*/
								player.setPlayerAnimation("stopped");
								player.stopAnimation(0);
								right.setScale(.5f);
								right.setAlpha(0.7f);
							}
						}
					}
					return true;
				}
			};
			right.setRotation(180f);
			right.setScale(.5f);
			right.setAlpha(0.7f);
			rightArea.setAlpha(0);

			gameHUD.registerTouchArea(leftArea);
			gameHUD.registerTouchArea(rightArea);
			gameHUD.attachChild(left);
			gameHUD.attachChild(leftArea);
			gameHUD.attachChild(right);
			gameHUD.attachChild(rightArea);
		}
		
		if (debugCollision) {
			// Collision Indicators (Temporary)
			collideRightIndicator = new Rectangle(GameActivity.CAMERA_WIDTH / 2+30,
					GameActivity.CAMERA_HEIGHT-50, 30,
					10, vbom);
			collideRightIndicator.setColor(Color.GREEN);
			gameHUD.attachChild(collideRightIndicator);
			collideLeftIndicator = new Rectangle(GameActivity.CAMERA_WIDTH / 2-30,
					GameActivity.CAMERA_HEIGHT-50, 30,
					10, vbom);
			collideLeftIndicator.setColor(Color.GREEN);
			gameHUD.attachChild(collideLeftIndicator);
			collideTopIndicator = new Rectangle(GameActivity.CAMERA_WIDTH / 2,
					GameActivity.CAMERA_HEIGHT-25, 10,
					30, vbom);
			collideTopIndicator.setColor(Color.GREEN);
			gameHUD.attachChild(collideTopIndicator);
			collideBottomIndicator = new Rectangle(GameActivity.CAMERA_WIDTH / 2,
					GameActivity.CAMERA_HEIGHT-75, 10,
					30, vbom);
			collideBottomIndicator.setColor(Color.GREEN);
			gameHUD.attachChild(collideBottomIndicator);
		}

		// Entire Screen?
		popupArea = new Rectangle(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2, GameActivity.CAMERA_WIDTH - 50,
				GameActivity.CAMERA_HEIGHT / 2, vbom) {
			public boolean onAreaTouched(TouchEvent touchEvent, float X, float Y) {
				if (touchEvent.isActionDown()) {
					if (popupIsShowing) {
						unpauseGame();
						popupIsShowing = false;
					} else if (levelEndDisplayed) {
						camera.setZoomFactor(1);
						SceneManager.getInstance().gameScene.disposeScene();
						ResourcesManager.getInstance().unloadGameTextures();
						SceneManager.getInstance().loadLevelSelectScene();
					}
				}
				return true;
			}
		};
		popupArea.setAlpha(0);
		gameHUD.attachChild(popupArea);
		gameHUD.registerTouchArea(popupArea);

		createLevelEndSprite();

		camera.setHUD(gameHUD);
	}

	/*
	 * private void addToScore(int i) { score += i; scoreText.setText("Score: "
	 * + score); }
	 */

	private void createPhysics() {
		// Set gravity, try to achieve 60 fps
		physicsWorld = new FixedStepPhysicsWorld(60, worldGravity, false);
		physicsWorld.setContactListener(contactListener());
		// Register physics world as an update handler to scene
		registerUpdateHandler(physicsWorld);
	}

	@Override
	protected void onManagedUpdate(float pSecondsElapsed) {
		if (slowMotionActive) {
			/*
			 * If slow motion is activated, call the superclass passing
			 * .5*pSecondsElapsed
			 */
			super.onManagedUpdate(pSecondsElapsed * 0.5f);
		} else {
			/*
			 * If slow motion is not activated, call the superclass passing
			 * pSecondsElapsed unaltered
			 */
			super.onManagedUpdate(pSecondsElapsed);
		}

		// Check if the player's scale meter needs to be adjusted
		if (player.scaling && player.scaleMeterAmount > 0) {
			// Player is scaling, decrement scale meter if possible
			player.scaleMeterAmount -= player.scaleDecrementAmount;
			scaleMeterBar.setWidth(player.scaleMeterAmount);
			scaleMeterBar.setX(scaleMeterBackground.getX()
					- (player.maxScaleMeterAmount / 2)
					+ (player.scaleMeterAmount / 2));
			player.timeWaited = 0;
		} else if (!player.scaling
				&& player.scaleMeterAmount < player.maxScaleMeterAmount) {
			// Player isn't scaling, increment scale meter if possible
			if (player.timeWaited < player.maxTimeWaited) {
				player.timeWaited++;
			} else {
				player.scaleMeterAmount += player.scaleDecrementAmount;
				scaleMeterBar.setWidth(player.scaleMeterAmount);
				scaleMeterBar.setX(scaleMeterBackground.getX()
						- (player.maxScaleMeterAmount / 2)
						+ (player.scaleMeterAmount / 2));
			}
		} else if (player.scaleMeterAmount <= 0) {
			// Player's scale meter hits zero, reset his scale amount
			player.scaling = false;
			Vector2 playerVelocity = player.body.getLinearVelocity(); // Get the initial velocity
			float oldScale = player.getScaleY();
			buttonScaleVisible.setY(120);
			buttonScaleArea.setY(120);
			player.changeScale((float) (player.playerScale * (Math.pow(1
					+ (buttonScaleVisible.getY() - slideScale.getY())
					/ (slideScale.getHeight()), 4))));
			/*player.setScale((float) (player.playerScale * (Math.pow(1
					+ (buttonScaleVisible.getY() - slideScale.getY())
					/ (slideScale.getHeight()), 4))));
			final PhysicsConnector pc = physicsWorld
					.getPhysicsConnectorManager().findPhysicsConnectorByShape(
							player);
			physicsWorld.unregisterPhysicsConnector(pc);
			physicsWorld.destroyBody(player.body);
			player.createPhysics(camera, physicsWorld);
			physicsWorld.registerPhysicsConnector(new PhysicsConnector(player,
					player.body, true, false) {
				// Use onUpdate method to help
				// reduce
				// camera jittering when moving
				@Override
				public void onUpdate(float pSecondsElapsed) {
					super.onUpdate(pSecondsElapsed);
					camera.onUpdate(0.1f);
				}
			});*/
			if (controlMethod == ARROW_CONTROL) {
				if (player.goingRight) {
					player.changeVelocity((float) (10 * Math.sqrt(player.getScaleY())),
							player.body.getLinearVelocity().y);
				} else if (player.goingLeft) {
					player.changeVelocity((float) (-10 * Math.sqrt(player.getScaleY())),
							player.body.getLinearVelocity().y);
				}
			} else if (controlMethod == SLIDER_CONTROL) {
				player.changeVelocity((float) ((buttonMoveVisible.getX() - slideMove
						.getX()) / 8 * Math
						.sqrt(player.getScaleY())), playerVelocity.y);
			} else if (controlMethod == JOYSTICK_CONTROL){
				float oldPValue = (float) (playerVelocity.x/10/Math.pow(oldScale, 2));
				player.changeVelocity((float) ((oldPValue) * 10 * Math.sqrt(player
						.getScaleY())), player.body
						.getLinearVelocity().y);
			}
			// Player.body.setUserData("player");
			// Zoom the camera in/out based on the scale
			camera.setZoomFactor((float) (1 / (Math.pow(
					1 + (buttonScaleVisible.getY() - slideScale.getY())
							/ (slideScale.getHeight()), .75))));
			player.collidingBottom = false;
			player.collidingRight = false;
			player.collidingTop = false;
			player.collidingLeft = false;
			if(debugCollision) {
				collideRightIndicator.setColor(Color.GREEN);
				collideLeftIndicator.setColor(Color.GREEN);
				collideBottomIndicator.setColor(Color.GREEN);
				collideTopIndicator.setColor(Color.GREEN);
			}

		}

		// Check if character falls beneath the level
		if (player.getY() <= minCameraY) {
			player.onDie();
		}
		// Check if any hints or dialogue are reached
		if (showHints) {
			for (int i = 0; i < popupTable.length; i++) {
				if ((Boolean) popupTable[i][0] == false
						&& player.getX() >= (Integer) popupTable[i][1]) {
					showPopup(i);
				}
			}
		}
		// Check if character reaches the end of the level
		if (!levelEndDisplayed && player.getX() >= levelWidth - 300) {
			displayLevelEnd();
		}
	}

	private void loadLevel(int levelID) {
		final SimpleLevelLoader levelLoader = new SimpleLevelLoader(vbom);

		final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0,
				0.01f); // Could be 0, .01f, 0.5f

		// Return entity where all loaded entities are going to be attached to
		// for all entities loaded from xml file
		levelLoader
				.registerEntityLoader(new EntityLoader<SimpleLevelEntityLoaderData>(
						LevelConstants.TAG_LEVEL) {
					public IEntity onLoadEntity(
							final String pEntityName,
							final IEntity pParent,
							final Attributes pAttributes,
							final SimpleLevelEntityLoaderData pSimpleLevelEntityLoaderData)
							throws IOException {
						final int width = SAXUtils.getIntAttributeOrThrow(
								pAttributes,
								LevelConstants.TAG_LEVEL_ATTRIBUTE_WIDTH);
						final int height = SAXUtils.getIntAttributeOrThrow(
								pAttributes,
								LevelConstants.TAG_LEVEL_ATTRIBUTE_HEIGHT);
						final int minScreenY = SAXUtils.getIntAttribute(
								pAttributes, TAG_LEVEL_ATTRIBUTE_MIN_SCREEN_Y,
								0);
						// Set camera bounds
						camera.setBounds(0, minScreenY, width, height);
						minCameraY = minScreenY;
						levelWidth = width;
						camera.setBoundsEnabled(true);

						return GameScene.this;
					}
				});

		// Parse file
		levelLoader
				.registerEntityLoader(new EntityLoader<SimpleLevelEntityLoaderData>(
						TAG_ENTITY) {
					public IEntity onLoadEntity(
							final String pEntityName,
							final IEntity pParent,
							final Attributes pAttributes,
							final SimpleLevelEntityLoaderData pSimpleLevelEntityLoaderData)
							throws IOException {
						final int x = SAXUtils.getIntAttribute(pAttributes,
								TAG_ENTITY_ATTRIBUTE_X, -1);
						final int y = SAXUtils.getIntAttribute(pAttributes,
								TAG_ENTITY_ATTRIBUTE_Y, -1);
						final String type = SAXUtils.getAttributeOrThrow(
								pAttributes, TAG_ENTITY_ATTRIBUTE_TYPE);
						final int width = SAXUtils.getIntAttribute(pAttributes,
								TAG_ENTITY_ATTRIBUTE_WIDTH, -1);
						final int height = SAXUtils.getIntAttribute(
								pAttributes, TAG_ENTITY_ATTRIBUTE_HEIGHT, -1);
						final int range = SAXUtils.getIntAttribute(pAttributes,
								TAG_ENTITY_ATTRIBUTE_RANGE, 50);
						final String myText = SAXUtils.getAttribute(
								pAttributes, TAG_ENTITY_ATTRIBUTE_WORDS, " ");
						final int delay = SAXUtils.getIntAttribute(pAttributes,
								TAG_ENTITY_ATTRIBUTE_DELAY, 0);
						final boolean collideWith = SAXUtils
								.getBooleanAttribute(pAttributes,
										TAG_ENTITY_ATTRIBUTE_COLLIDE_WITH,
										false);
						final String purpose = SAXUtils.getAttribute(
								pAttributes,
								TAG_ENTITY_ATTRIBUTE_POPUP_PURPOSE, "dialogue");

						if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLAYER)) {
							player = new Player(x, y, resourcesManager.player_texture_region, 
									vbom, camera, physicsWorld) {
								@Override
								public void onDie() {
									if (!gameOverDisplayed
											&& !levelEndDisplayed) {
										player.alive = false;
										if (player.footContacts >= 1) {
											player.stopRunning();
										}
										displayGameOverText();
										// Hide HUD
										// camera.getHUD().setVisible(false);
									}
								}
							};
							// Better to use player.changeScale(player.playerScale)? This registers a physics body. Better for maintainability
							player.setScale(player.playerScale);
							player.createPhysics(camera, physicsWorld);
							player.footContacts=0;
							camera.setChaseEntity(player); // Camera will follow player's position
							physicsWorld
									.registerPhysicsConnector(new PhysicsConnector(
											player, player.body, true, false) {
										// Use onUpdate method to help reduce
										// camera jittering when moving
										@Override
										public void onUpdate(
												float pSecondsElapsed) {
											super.onUpdate(pSecondsElapsed);
											camera.onUpdate(0.1f);

											// Check if character falls beneath
											// the level
											if (this.getEntity().getY() <= minCameraY) {
												player.onDie();
											}
											if (showHints) {
												// 
												for (int i = 0; i < popupTable.length; i++) {
													if ((Boolean) popupTable[i][0] == false
															&& this.getEntity()
																	.getX() >= (Integer) popupTable[i][1]) {
														showPopup(i);
													}
												}
											}
											if (!levelEndDisplayed
													&& this.getEntity().getX() >= levelWidth - 300) {
												displayLevelEnd();
											}
										}
									});
							// TODO
							player.setPlayerAnimation("stopped");
							player.stopRunning();
							Sprite levelObject = player;
							levelObject.setCullingEnabled(true);
							return levelObject;
						} else if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_TURRET)) {
							// Draw the base for the turret
							final Sprite TurretBase = new Sprite(x+10,
									y+15, ResourcesManager.getInstance().turret_base_region, vbom);
							TurretBase.setScale(0.25f);
							attachChild(TurretBase);
							
							// Add the turret
							final Turret levelObject = new Turret(x, y, vbom, engine);
							levelObject.setRotationCenter(0.5f, 0.5f);
							
							// Bounds of rotation
							// Remember: Physics bodies use radians, sprites use degrees
							final float startRotation = 0.0f;
							final float stopRotation = 45.0f;
							
							// Add the laser
							final Rectangle mLaser = new Rectangle(x-100, y+40, 200, 2, vbom);
							mLaser.setAlpha(0.6f);
							mLaser.setColor(Color.RED);
							/*mLaser.registerEntityModifier(
									new RotationModifier(3, startRotation, stopRotation));*/
							mLaser.setRotationCenter(1f, 0.5f);	// Have the laser rotate with the same center as the turret
							//mLaser.setRotation(startRotation);
							final FixtureDef areaFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 0);
							areaFixtureDef.isSensor = true;
							final Body laserBody = PhysicsFactory.createBoxBody(physicsWorld, mLaser, BodyType.KinematicBody, areaFixtureDef);
							//laserBody.getMassData().center.set(laserBody.getLocalPoint(new Vector2(x+100, y+40)));
							laserBody.setUserData(mLaser);
							//laserBody.setTransform(new Vector2(mLaser.getX(), mLaser.getY()), mLaser.getRotation());
							laserBody.setFixedRotation(false);
							physicsWorld.registerPhysicsConnector(new PhysicsConnector(
									mLaser, laserBody, true, true) {
								@Override
								public void onUpdate(
										float pSecondsElapsed) {
									super.onUpdate(pSecondsElapsed);
									/*final PhysicsConnector pc = physicsWorld
											.getPhysicsConnectorManager()
											.findPhysicsConnectorByShape(mLaser);
									GameScene.physicsWorld.unregisterPhysicsConnector(pc);
									physicsWorld.destroyBody(laserBody);
									final Body laserBody = PhysicsFactory.createBoxBody(physicsWorld, mLaser, BodyType.KinematicBody, areaFixtureDef);
									laserBody.setUserData(mLaser);*/
									/*Log.d("Laser start rotation", Float.toString(laserBody.getAngle()));
									if(laserBody.getAngle() >= startRotation) {
										laserBody.setAngularVelocity(-0.6f);
									} else if (laserBody.getAngle() <= stopRotation) {
										laserBody.setAngularVelocity(0.6f);
									}*/
									//Log.d("Laser rotation", Float.toString(mLaser.getRotation()));
									if(mLaser.getRotation() == startRotation) {
										Log.d("Laser start rotation", Float.toString(mLaser.getRotation()));
										mLaser.registerEntityModifier(
												new RotationModifier(3, startRotation, stopRotation));
										//laserBody.setTransform(new Vector2(mLaser.getX(), mLaser.getY()), mLaser.getRotation());
									} else if (mLaser.getRotation() == stopRotation) {
										Log.d("Laser start rotation", Float.toString(mLaser.getRotation()));
										mLaser.registerEntityModifier(
												new RotationModifier(3, stopRotation, startRotation));
										//laserBody.setTransform(new Vector2(mLaser.getX(), mLaser.getY()), mLaser.getRotation());
									}
									/*if (mLaser.laserHit) {
										mLaser.laserHit = false;
										levelObject.fireBullet();
									}*/
								}
							});
							mLaser.setCullingEnabled(true);
							attachChild(mLaser);
							
							// Add the body for the turret
							final Body body = PhysicsFactory.createBoxBody(
									physicsWorld, levelObject,
									BodyType.KinematicBody, FIXTURE_DEF);
							body.setUserData("turret");
							physicsWorld
							.registerPhysicsConnector(new PhysicsConnector(
									levelObject, body, true, true) {
								@Override
								public void onUpdate(
										float pSecondsElapsed) {
									super.onUpdate(pSecondsElapsed);
									/*if(body.getAngle() >= startRotation) {
										//Log.d("Turret start rotation", Float.toString(startRotation));
										body.setAngularVelocity(-0.6f);
									} else if (body.getAngle() <= -(float) Math.toRadians(stopRotation)) {
										body.setAngularVelocity(0.6f);
									}*/
									//Log.d("Turret rotation", Float.toString(levelObject.getRotation()));
									if(levelObject.getRotation() == startRotation) {
										levelObject.registerEntityModifier(
												new RotationModifier(3, startRotation, stopRotation));
									} else if (levelObject.getRotation() == stopRotation) {
										levelObject.registerEntityModifier(
												new RotationModifier(3, stopRotation, startRotation));
									}
								}
							});
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_DRONE)) {
							final Drone levelObject = new Drone(x, y, vbom);
							levelObject.setCullingEnabled(true);
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_MOVING_PLATFORM)) {
							final Rectangle levelObject = new Rectangle(x
									+ width / 2, y + height / 2, width, height,
									vbom);
							levelObject.setColor(Color.BLACK);
							final Body body = PhysicsFactory.createBoxBody(
									physicsWorld, levelObject,
									BodyType.KinematicBody, FIXTURE_DEF);
							body.setUserData("movingPlatform");
							body.setLinearVelocity(-5, 0);
							body.getFixtureList().get(0).setFriction(1000f);
							physicsWorld
									.registerPhysicsConnector(new PhysicsConnector(
											levelObject, body, true, false) {
										@Override
										public void onUpdate(
												float pSecondsElapsed) {
											super.onUpdate(pSecondsElapsed);
											if (levelObject.getX() <= x - range
													/ 2) {
												body.setLinearVelocity(5, 0);
											} else if (levelObject.getX() >= x
													+ range / 2) {
												body.setLinearVelocity(-5, 0);
											}
										}
									});
							levelObject.setCullingEnabled(true);
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_RECTANGLE)) {
							// 
							Terrain levelObject = new Terrain(
									x + width / 2, y + height / 2, width,
									height, vbom);
							levelObject.setColor(Color.BLACK);
							final Body body = PhysicsFactory.createBoxBody(
									physicsWorld, levelObject,
									BodyType.StaticBody, FIXTURE_DEF);
							body.setUserData(levelObject);
							physicsWorld
									.registerPhysicsConnector(new PhysicsConnector(
											levelObject, body, true, false));
							levelObject.setCullingEnabled(true);
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_MOVING_BOX)) {
							Rectangle levelObject = new Rectangle(
									x + width / 2, y + height / 2, width,
									height, vbom);
							levelObject.setColor(Color.BLACK);
							FixtureDef FIXTURE_DEF_BOX = PhysicsFactory.createFixtureDef(0, 0,
									0.3f);
							final Body body = PhysicsFactory.createBoxBody(
									physicsWorld, levelObject,
									BodyType.DynamicBody, FIXTURE_DEF_BOX);
							body.setUserData("rectangle");
							physicsWorld
									.registerPhysicsConnector(new PhysicsConnector(
											levelObject, body, true, true));
							levelObject.setCullingEnabled(true);
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_POWERUP)) {
							Sprite levelObject = new Sprite(x, y,
									resourcesManager.powerup_region, vbom) {
								@Override
								protected void onManagedUpdate(
										float pSecondsElapsed) {
									super.onManagedUpdate(pSecondsElapsed);

									if (player.collidesWith(this)) {
										//addToScore(10); // Increase score
										// Turn invisible
										this.setVisible(false);
										// Set to ignore update so it won't
										// update anymore
										this.setIgnoreUpdate(true);
										numPowerupsCollected++;
									}
								}
							};
							levelObject
									.registerEntityModifier(new LoopEntityModifier(
											new ScaleModifier(1, .5f, .6f)));
							levelObject
								.registerEntityModifier(new LoopEntityModifier(
									new AlphaModifier(1, 0, 1)));
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_TEXT)) {
							Text levelObject = null;
							if (storyBoxChecked) { // Set text if plot is turned
													// on
								levelObject = new Text(
										x,
										y,
										resourcesManager.font,
										"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
										new TextOptions(HorizontalAlign.LEFT),
										vbom);
								levelObject.setText(myText);
								levelObject.setColor(Color.BLACK);
								// Allows a collider to be added to the words
								if (collideWith) {
									final Body body = PhysicsFactory
											.createBoxBody(physicsWorld,
													levelObject,
													BodyType.StaticBody,
													FIXTURE_DEF);
									body.setUserData("words");
									physicsWorld
											.registerPhysicsConnector(new PhysicsConnector(
													levelObject, body, true,
													false));
								}
							}
							// int textLength = measureText(levelObject);
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_SPIKES)) {
							Rectangle levelObject = new Rectangle(
									x + width / 2, y + height / 2, width,
									height, vbom);
							addSpikes(x, y, width, height);
							levelObject.setColor(Color.BLACK);
							levelObject.setAlpha(1);

							final Body body = PhysicsFactory.createBoxBody(
									physicsWorld, levelObject,
									BodyType.StaticBody, FIXTURE_DEF);
							body.setUserData("spikes");
							physicsWorld
									.registerPhysicsConnector(new PhysicsConnector(
											levelObject, body, true, false));
							return levelObject;
						} else if (type
								.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_POPUP)) {
							// 
							Text LevelObject = null;
							if ((purpose.equalsIgnoreCase("hint") && hintBoxChecked)
									|| (purpose .equalsIgnoreCase("dialogue") && storyBoxChecked)) {
								showHints = true;
//								if (x == 0) {
//									popupText.setText(myText);
//									showPopup(popupIndex);// delay);
//								} else {
									popupTable[popupIndex][0] = false;
									popupTable[popupIndex][1] = x;
									popupTable[popupIndex][2] = delay;
									popupTable[popupIndex][3] = myText;
									popupTable[popupIndex][4] = purpose;
									popupIndex++;
								//}
							}
							return LevelObject;
						} else {
							throw new IllegalArgumentException();
						}
					}
				});

		// levelLoader.loadLevelFromAsset(activity.getAssets(), "level/" +
		// levelID + ".lvl");
		levelLoader.loadLevelFromAsset(activity.getAssets(), "level/" + levelID
				+ ".txt");
	}

	/*
	 * public boolean onSceneTouchEvent(Scene pScene, TouchEvent
	 * pSceneTouchEvent) { //if (pSceneTouchEvent.isActionDown()) { //if
	 * (!firstTouch) { //player.setRunning(); //firstTouch = true; //} else {
	 * //player.jump(); //} //} return false; }
	 */

	protected void addSpikes(int x, int y, int width, int height) {
		// Adds horizontal spikes to the game. Width should be greater than
		// height, and divisible
		int numSpikes = width / height;
		Rectangle[] childSpike = new Rectangle[numSpikes];
		for (int i = 0; i < numSpikes; i++) {
			childSpike[i] = new Rectangle(x + (i * width / numSpikes)
					+ ((width / numSpikes) / 2), y + height / 2, width
					/ numSpikes, height, vbom);
			childSpike[i].setRotation(45f);
			childSpike[i].setColor(Color.BLACK);
			childSpike[i].setCullingEnabled(true);
			attachChild(childSpike[i]);
		}
	}

	public void showPopup(int index) {
		// 
		int delay = (Integer) popupTable[index][2];
		
		popupTable[index][0] = true;
		popupText.setText((String) popupTable[index][3]);
		if (((String) popupTable[index][4]).equals("hint")) {
			hintRectangle.setVisible(true);
			dialogueRectangle.setVisible(false);
		} else {
			hintRectangle.setVisible(false);
			dialogueRectangle.setVisible(true);
		}
		
		if (delay==0) {
			popupIsShowing = true;
			setChildScene(mPopupScene, false, true, true);
			setIgnoreUpdate(true);
			if (controlMethod == SLIDER_CONTROL) {
				buttonMoveVisible.setAlpha(0);
				slideMove.setAlpha(0);
			} else if (controlMethod == ARROW_CONTROL) {
				left.setAlpha(0);
				right.setAlpha(0);
				if (player.goingRight && !player.goingLeft) {
					right.setAlpha(0);
				} else if (player.goingLeft && !player.goingRight) {
					left.setAlpha(0);
				}
			}
			slideScale.setAlpha(0);
			buttonScaleVisible.setAlpha(0);
			jumpButtonVisible.setAlpha(0);
			pauseButton.setAlpha(0);
			scaleMeterBackground.setAlpha(0);
			scaleMeterBar.setAlpha(0);
		} else {
			float newDelay = (float) delay;
			registerUpdateHandler(new TimerHandler(newDelay, false,
					new ITimerCallback() {
						@Override
						public void onTimePassed(TimerHandler pTimerHandler) {
							popupIsShowing = true;
							setChildScene(mPopupScene, false, true, true);
							setIgnoreUpdate(true);
							if (controlMethod == SLIDER_CONTROL) {
								buttonMoveVisible.setAlpha(0);
								slideMove.setAlpha(0);
							} else if (controlMethod == ARROW_CONTROL) {
								left.setAlpha(0);
								right.setAlpha(0);
								if (player.goingRight && !player.goingLeft) {
									right.setAlpha(0);
								} else if (player.goingLeft
										&& !player.goingRight) {
									left.setAlpha(0);
								}
							}
							slideScale.setAlpha(0);
							buttonScaleVisible.setAlpha(0);
							jumpButtonVisible.setAlpha(0);
							pauseButton.setAlpha(0);
							scaleMeterBackground.setAlpha(0);
							scaleMeterBar.setAlpha(0);
						}
					}));
		}
	}

	public void pauseGame() {
		isPaused = true;
		setChildScene(mPauseScene, false, true, true);
		setIgnoreUpdate(true);

		// resourcesManager.pause_button_region.setCurrentTileIndex(1);
		// playButton = new Sprite(45, GameActivity.CAMERA_HEIGHT-45,
		// ResourcesManager.pause_button_region, vbom);
		playButton.setAlpha(0.8f);
		pauseButton.setAlpha(0);

		// pauseButton.setScale(0.5f);
		// pauseButton.setAlpha(0.8f);
		// gameHUD.attachChild(pauseButton);
		// engine.stop();

		if (controlMethod == SLIDER_CONTROL) {
			buttonMoveVisible.setAlpha(0);
			// gameHUD.unregisterTouchArea(buttonMoveArea);
			slideMove.setAlpha(0);
		} else if (controlMethod == ARROW_CONTROL) {
			left.setAlpha(0);
			right.setAlpha(0);
		}
		slideScale.setAlpha(0);
		buttonScaleVisible.setAlpha(0);
		jumpButtonVisible.setAlpha(0);
		scaleMeterBackground.setAlpha(0);
		scaleMeterBar.setAlpha(0);
	}

	public void unpauseGame() {
		isPaused = false;
		popupIsShowing = false;
		clearChildScene();
		if (controlMethod == JOYSTICK_CONTROL) {
			setChildScene(analogOnScreenControl);
		}
		setIgnoreUpdate(false);

		playButton.setAlpha(0);
		pauseButton.setAlpha(0.8f);
		if (controlMethod == SLIDER_CONTROL) {
			buttonMoveVisible.setAlpha(.5f);
			slideMove.setAlpha(.5f);
		} else if (controlMethod == ARROW_CONTROL) {
			left.setAlpha(.7f);
			right.setAlpha(.7f);
			if (player.goingRight && !player.goingLeft) {
				right.setAlpha(.9f);
			} else if (player.goingLeft && !player.goingRight) {
				left.setAlpha(.9f);
			}
		}
		slideScale.setAlpha(.5f);
		buttonScaleVisible.setAlpha(.4f);
		jumpButtonVisible.setAlpha(.8f);
		scaleMeterBackground.setAlpha(0.6f);
		scaleMeterBar.setAlpha(1);
	}

	private void createGameOverText() {
		gameOverText = new Text(0, 0, resourcesManager.font, "Game Over", vbom);
		gameOverText.setColor(Color.WHITE);
	}

	private void displayGameOverText() {
		camera.setChaseEntity(null); // Disable camera chasing character
		gameOverText.setPosition(camera.getCenterX(), camera.getCenterY());
		attachChild(gameOverText);
		gameOverDisplayed = true;
		// camera.getHUD().setVisible(false);
	}

	private void displayLevelEnd() {
		camera.setChaseEntity(null);
		levelEndDisplayed = true;
		gameHUD.attachChild(levelEndRectangle);
		gameHUD.attachChild(levelEndText);
		gameOverDisplayed = true;
		player.alive = false;
		
		// Check if player collected more powerups than previously
		int numNewPowerups = numPowerupsCollected - levelPowerupsArray[SceneManager.getInstance().whichLevel-1];
		if(numNewPowerups > 0) {
			// Save the new highest number of powerups collected
			mySavedData.saveData("LEVEL_POWERUPS_COLLECTED"+(SceneManager.getInstance().whichLevel), numPowerupsCollected);
			// Increase player's experience based on the number of new powerups they've collected
			playerExperience += POWERUP_EXPERIENCE_BONUS * numNewPowerups;
			mySavedData.saveData("PLAYER_EXPERIENCE", playerExperience);
		}
		
		// Check if level was completed previously
		if (levelCompleteArray[SceneManager.getInstance().whichLevel] == false) {
			// Save that the level was completed
			mySavedData.saveData("LEVEL_COMPLETE"
					+ SceneManager.getInstance().whichLevel, true);
			// Increase player's experience if they've completed a new level
			mySavedData.saveData("PLAYER_EXPERIENCE", playerExperience + LEVEL_COMPLETE_EXPERIENCE_BONUS);
		}
		mySavedData.loadProgressData();
		// camera.getHUD().setVisible(false);
	}

	// Contact Listener lets execute code while events such as contact begin/end
	// between fixtures occur.
	private ContactListener contactListener() {
		contactListener = new ContactListener() {
			// On every begin contact
			public void beginContact(Contact contact) {
				final Fixture x1 = contact.getFixtureA();
				final Fixture x2 = contact.getFixtureB();

				// Use if/else if's or if/if's?

				// Check if there is user data
				if (x1.getBody().getUserData() != null
						&& x2.getBody().getUserData() != null) {
					// 
					Body playerBody = null;
					Body collideBody = null;
					
					// Check if one of the bodies is the player
					if (x1.getBody().getUserData().equals("player")) {
						playerBody = x1.getBody();
						collideBody = x2.getBody();
					} else if (x2.getBody().getUserData().equals("player")) {
						playerBody = x2.getBody();
						collideBody = x1.getBody();
					}
					if (collideBody != null && playerBody != null) {
						// Check if colliding with terrain
						if(collideBody.getUserData().getClass().getSimpleName().equals("Terrain")) {
							Terrain contactTerrain = (Terrain) collideBody.getUserData();
							
							// Get bounds of player
							float playerRightEdge = player.getX() + player.getScaledWidth()/2;
							float playerLeftEdge = player.getX() - player.getScaledWidth()/2;
							float playerTopEdge = player.getY() + player.getScaledHeight()/2;
							float playerBottomEdge = player.getY() - player.getScaledHeight()/2;
							//Log.d(Float.toString(playerBottomEdge), "Player Bottom Edge");
							
							// Get bounds of terrain
							float terrainRightEdge = contactTerrain.getX() + contactTerrain.getWidth()/2;
							float terrainLeftEdge = contactTerrain.getX() - contactTerrain.getWidth()/2;
							float terrainTopEdge = contactTerrain.getY() + contactTerrain.getHeight()/2;
							float terrainBottomEdge = contactTerrain.getY() - contactTerrain.getHeight()/2;
							//Log.d(Float.toString(terrainTopEdge), "Terrain Top Edge");
							
							// Check for Player colliding on bottom edge
							if (playerBottomEdge >= terrainTopEdge && (playerLeftEdge < terrainRightEdge || playerRightEdge > terrainLeftEdge)) {
								//Log.d("Colliding Bottom", "Colliding Bottom");
								player.collideBottomNum++;
								player.collidingBottom = true;
								if(debugCollision) {
									collideBottomIndicator.setColor(Color.RED);
								}
								player.increaseFootContacts();
							}
							// Check for Player colliding on his right edge
							else if (playerRightEdge <= terrainLeftEdge && (playerTopEdge > terrainBottomEdge || playerBottomEdge < terrainTopEdge)) {
								player.collideRightNum++;
								player.collidingRight = true;
								if(debugCollision) {
									collideRightIndicator.setColor(Color.RED);
								}
							}
							// Check for player colliding on top edge
							else if (playerTopEdge <= terrainBottomEdge && (playerRightEdge > terrainLeftEdge || playerLeftEdge < terrainRightEdge)) {
								player.collideTopNum++;
								player.collidingTop = true;
								if(debugCollision) {
									collideTopIndicator.setColor(Color.RED);
								}
							}
							// Check for player colliding on left edge
							else if (playerLeftEdge >= terrainRightEdge && (playerTopEdge > terrainBottomEdge || playerBottomEdge < terrainTopEdge)) {
								player.collideLeftNum++;
								player.collidingLeft = true;
								if(debugCollision) {
									collideLeftIndicator.setColor(Color.RED);
								}
							}
						} else if (collideBody.getUserData().equals("spikes")) {
							// If he collides with spikes, game over
							player.onDie();
						} else if (collideBody.getUserData().getClass().getSimpleName().equals("Drone")) {
							player.onDie();
						} else if(collideBody.getUserData().getClass().getSimpleName().equals("Laser")) {
							Laser contactLaser = (Laser) collideBody.getUserData();
							contactLaser.laserHit = true;
						} else {
							//Get the normal to the contact
							float directionX = contact.getWorldManifold().getNormal().x; 
							float directionY = contact.getWorldManifold().getNormal().y;
		
							// Check if the player is colliding with something, and in
							// which direction
							Vector2 playerPos = playerBody.getPosition();
							Vector2 blockPos = collideBody.getPosition();
		
							if (playerPos.y > blockPos.y && directionY != 0.0f
									&& !player.collidingBottom) // Player above block,
																// colliding on bottom
							{
								player.collideBottomNum++;
								player.collidingBottom = true;
								if(debugCollision) {
									collideBottomIndicator.setColor(Color.RED);
								}
								player.increaseFootContacts();
							}
							if (playerPos.y < blockPos.y && directionY != 0.0f
									&& !player.collidingTop) // Player below block,
																// colliding on top
							{
								player.collideTopNum++;
								player.collidingTop = true;
								if(debugCollision) {
									collideTopIndicator.setColor(Color.RED);
								}
							}
							if (playerPos.x < blockPos.x && directionX != 0.0f
									&& !player.collidingRight) // Player to the left of
																// block, colliding on
																// the right
							{
								player.collideRightNum++;
								player.collidingRight = true;
								if(debugCollision) {
									collideRightIndicator.setColor(Color.RED);
								}
							}
							if (playerPos.x > blockPos.x && directionX != 0.0f
									&& !player.collidingLeft) // Player to the right of
																// block, colliding on
																// the left
							{
								player.collideLeftNum++;
								player.collidingLeft = true;
								if(debugCollision) {
									collideLeftIndicator.setColor(Color.RED);
								}
							}
						}
					}
				}
			}

			public void endContact(Contact contact) {
				final Fixture x1 = contact.getFixtureA();
				final Fixture x2 = contact.getFixtureB();

				if (x1.getBody().getUserData() != null
						&& x2.getBody().getUserData() != null) {
					Body playerBody = null;
					Body collideBody = null;
					
					// Check if one of the bodies is the player
					if (x1.getBody().getUserData().equals("player")) {
						playerBody = x1.getBody();
						collideBody = x2.getBody();
					} else if (x2.getBody().getUserData().equals("player")) {
						playerBody = x2.getBody();
						collideBody = x1.getBody();
					}
					if (collideBody != null && playerBody != null) {
						if(!collideBody.getUserData().equals("spikes") && !collideBody.getUserData().getClass().getSimpleName().equals("Drone") && !collideBody.getUserData().getClass().getSimpleName().equals("Laser")) {
							// Get the normal to the contact
							float directionX = contact.getWorldManifold().getNormal().x; 
							float directionY = contact.getWorldManifold().getNormal().y;
							// Collision normal doesn't give angle fixtures collided at,
							// only fastest direction to separate. Use
							// getLinearVelocityFromWorld...
							Vector2 playerPos = playerBody.getPosition(); // Store
																			// the
																			// player's
																			// position
							Vector2 blockPos = collideBody.getPosition(); // Store
																		// position
																		// of
																		// what the
																		// player
																		// was
																		// colliding
																		// with
		
							if (playerPos.y > blockPos.y && directionY != 0.0f
									&& player.collidingBottom) // Player above
																// block,
																// colliding on
																// bottom
							{
								player.collideBottomNum--;
								if(player.collideBottomNum == 0) {
									player.collidingBottom = false;
									if(debugCollision) {
										collideBottomIndicator.setColor(Color.GREEN);
									}
								}
								// TODO: ISSUE WHEN RUNNING BETWEEN RECTANGLES
								player.decreaseFootContacts();
								if(player.footContacts <= 0 && player.playerState != Player.JUMPING_FORWARD && player.playerState != Player.JUMPING_UP) {
									player.setFalling();
								}
								// player.setJumping();
							}
							if (playerPos.y < blockPos.y && directionY != 0.0f
									&& player.collidingTop) // Player below block,
															// colliding on top
							{
								player.collideTopNum--;
								if(player.collideTopNum == 0) {
									player.collidingTop = false;
									if(debugCollision) {
										collideTopIndicator.setColor(Color.GREEN);
									}
								}
							}
							if (playerPos.x < blockPos.x && directionX != 0.0f
									&& player.collidingRight) // Player to the left
																// of
																// block, colliding
																// on
																// the right
							{
								player.collideRightNum--;
								if(player.collideRightNum == 0) {
									player.collidingRight = false;
									if(debugCollision) {
										collideRightIndicator.setColor(Color.GREEN);
									}
								}
							}
							if (playerPos.x > blockPos.x && directionX != 0.0f
									&& player.collidingLeft) // Player to the right
																// of
																// block, colliding
																// on
																// the left
							{
								player.collideLeftNum--;
								if(player.collideLeftNum == 0) {
									player.collidingLeft = false;
									if(debugCollision) {
										collideLeftIndicator.setColor(Color.GREEN);
									}
								}
							}
		
							// When contact ends, reset player velocity, because
							// character could be stopped
							if (controlMethod == ARROW_CONTROL) {
								if (player.goingRight) {
									player.changeVelocity((float) (10 * Math.sqrt(player
											.getScaleY())), player.body
											.getLinearVelocity().y);
									/*player.body.setLinearVelocity(new Vector2(
											(float) (10 * Math.sqrt(player
													.getScaleY())), player.body
													.getLinearVelocity().y));*/
								} else if (player.goingLeft) {
									player.changeVelocity((float) (-10 * Math.sqrt(player
											.getScaleY())), player.body
											.getLinearVelocity().y);
									/*player.body.setLinearVelocity(new Vector2(
											(float) (-10 * Math.sqrt(player
													.getScaleY())), player.body
													.getLinearVelocity().y));*/
								}
							} else if (controlMethod == SLIDER_CONTROL) {
								player.changeVelocity((float) ((buttonMoveVisible.getX() - slideMove
										.getX()) / 8 * Math
										.sqrt(player.getScaleY())), player.body.getLinearVelocity().y);
								/*player.body
										.setLinearVelocity(new Vector2(
												(float) ((buttonMoveVisible.getX() - slideMove
														.getX()) / 8 * Math
														.sqrt(player.getScaleY())),
												player.body.getLinearVelocity().y));*/
							}
						}
					}
				}
			}

			public void preSolve(Contact contact, Manifold oldManifold) {

			}

			public void postSolve(Contact contact, ContactImpulse impulse) {

			}
		};
		return contactListener;
	}

}
